home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Internet Tools 1993 July / Internet Tools.iso / RockRidge / mail / mm / mm-0.90 / mm-trans.c < prev    next >
Encoding:
C/C++ Source or Header  |  1990-12-18  |  7.5 KB  |  263 lines

  1. /*
  2.  * Copyright (c) 1986, 1990 by The Trustees of Columbia University in
  3.  * the City of New York.  Permission is granted to any individual or
  4.  * institution to use, copy, or redistribute this software so long as it
  5.  * is not sold for profit, provided this copyright notice is retained.
  6.  */
  7.  
  8. #ifndef lint
  9. static char *rcsid = "$Header: /f/src2/encore.bin/cucca/mm/tarring-it-up/RCS/mm-trans.c,v 2.1 90/10/04 18:24:55 melissa Exp $";
  10. #endif
  11.  
  12. /*
  13.  * transform:  Transform a mail.txt format file brought over from the
  14.  * 20 with ftp to fix the byte counts.  Since the 20's have CR/LF and
  15.  * the UNIX's only have LF, ftp strips out the CRs.  This messes up the
  16.  * byte counts in mail.txt format files.  Try to figure out where the
  17.  * message ends and fix them up.
  18.  *
  19.  * For now, read from argv[1] and write to stdout, like good Unix program.
  20.  * So say "transform mail-20.txt > mail-unix.txt".
  21.  *
  22.  * Note that this program is not yet very robust, but it does do the job.
  23.  * for example, it must read from a real file, or it can't get the size
  24.  * and read the whole thing in at once.
  25.  *
  26.  * Add Michael A. Cooper's modifications to also convert SRI UNIX-MM
  27.  * mail.txt files into Columbia Unix MM format.  The SRI MM uses the
  28.  * byte count only as a guess as to where the end of message is.
  29.  *
  30.  * Revised at University of Chicago by Jim Lichtenstein and Sam Gassel
  31.  * May, 1989.  Extensive rewrite of main loop, pointers for
  32.  * backtracking added, etc.  Older MM's use nulls as part of the
  33.  * message separators, so the original routine which dies on nulls
  34.  * became completely unacceptable.  Now nulls are changed to blanks.
  35.  */
  36.  
  37. #include "config.h"
  38. #include "osfiles.h"
  39. #include "compat.h"
  40. #include <ctype.h>
  41.  
  42. char *index (), *rindex ();
  43.  
  44. #define FALSE (0)
  45. #define TRUE (!FALSE)
  46.  
  47. #define hdrlen 81            /* the header's less than 80 chars */
  48. int msgnum = 0;                    /* which message we're up to */
  49.  
  50. main (argc,argv)
  51. int argc;
  52. char **argv;
  53. {
  54.     struct stat statb;
  55.     FILE *filep, *outfile;
  56.  
  57.     char *hdrptr;            /* what's left of the mail file */
  58.     char *date, *txt_size, *flags, *text; /* the pieces of a message */
  59.     char *c,*endhdr;                    /* moving utility pointer */
  60.  
  61.     int msg_size;            /* believed message size */
  62.     char *endbuf;
  63.  
  64.     if ((argc != 2) && (argc != 3)) {
  65.     fprintf (stderr, "usage: %s filename filename\n", argv[0]);
  66.     exit (1);
  67.     }
  68.  
  69.     /* Get total length of file for mallocing */
  70.     if (stat (argv[1],&statb) != 0) {    /* we need the length */
  71.     perror (argv[1]);
  72.     exit(1);
  73.     }
  74.  
  75.     /* Open it for reading */
  76.     if ((filep = fopen (argv[1], "r")) == NULL) {
  77.     perror (argv[1]);
  78.     exit(1);
  79.     }
  80.  
  81.     /*
  82.      * Make sure the file contains some data.
  83.      */
  84.     if (statb.st_size == 0) {
  85.     fprintf (stderr, "Original file is empty.\n");
  86.     exit(1);
  87.       }
  88.     /* get the whole file */
  89.     if ((hdrptr = (char *) malloc (statb.st_size +1)) == NULL) {
  90.     fprintf (stderr, "%s: File too big for internal buffer.\n", argv[1]);
  91.     exit(1);
  92.     }
  93.     hdrptr[statb.st_size] = '\0';    /* mark the ned with null */
  94.     if (fread (hdrptr, sizeof (char), statb.st_size, filep) != statb.st_size) {
  95.     perror (argv[1]);
  96.     exit(1);
  97.     }
  98.     endbuf = hdrptr+statb.st_size;
  99.     fclose(filep);            /* we have all the data now */
  100.  
  101.     /* change nulls to blanks */
  102.     for(c=hdrptr; c != endbuf; c++) {
  103.     if (*c == '\0') *c = ' ';
  104.     }
  105.  
  106.     /*
  107.      *  See if this mail file has been transformed already.
  108.      *  If so, let them know
  109.      */
  110.     if (alreadyTransformed(hdrptr))
  111.         fprintf(stderr,
  112.         "File looks already transformed, transforming anyway...\n");
  113.  
  114.     /* do this after reading infile, in case infile = outfile */
  115.     if (argc == 3) {
  116.     if ((outfile = fopen (argv[2], "w")) == NULL) {
  117.         perror (argv[2]);
  118.         exit(1);
  119.     }
  120.     }
  121.     else
  122.     outfile = stdout;        /* be a nice unix program */
  123.  
  124.     /* The first line does have to be right */
  125.     if (!ishead(hdrptr))
  126.     fail(msgnum);
  127.  
  128.     while (++msgnum) {            /* do next message */
  129.  
  130.     date = hdrptr;            /* header starts here */
  131.     txt_size = index (hdrptr, ',') + 1; /* these have to be... */
  132.     flags = index (hdrptr, ';') + 1; /* ... in the first line */
  133.     text = index (hdrptr, '\n') + 1; /* the line after the header */
  134.     if (txt_size > text || flags > text ||
  135.         (text - 1) == NULL || (flags - 1) == NULL || 
  136.         (txt_size - 1) == NULL) {
  137.         fprintf (stderr, "Errors in header line\n");
  138.         fail (msgnum);
  139.     }
  140.  
  141.     msg_size = atoi (txt_size);
  142.     /* we want to see if we got a negative number or a non-number */
  143.     /* a non-number gives value 0 */
  144.     if ((msg_size < 1) && (*txt_size != '0')) { /* really zero is okay */
  145.         fprintf (stderr, "Illegal size value.\n");
  146.         fail (msgnum);
  147.     }
  148.  
  149.     endhdr = text;
  150.  
  151.         /* msg_size counted CR and LF, so count each LF an extra time */
  152.     for (c = text; (c < text+msg_size) && (c != endbuf); c++) {
  153.         if (*c == '\n')
  154.         msg_size--;
  155.     }
  156.  
  157.     if ((c != endbuf) && (!ishead(c))) {
  158.         /*
  159.          * header not where we expected: could be nearer or farther, so
  160.          * move to beginning of message and search till we find it
  161.          */
  162.         fprintf(stderr, "\
  163. Warning: message length error in message #%d, backtracking...\n", msgnum);
  164.         for (c = text; !ishead(c) && c != endbuf; c++)
  165.         for(; *c != '\n'; c++)
  166.             ;
  167.         msg_size = c - text;
  168.     }
  169.  
  170.     /* We've reached the msg end and are ready to write it out*/
  171.     fwrite (date, sizeof (char), txt_size - date, outfile); /* date, */
  172.     fprintf (outfile, "%d;", msg_size); /* length of message; */
  173.     fwrite (flags, sizeof(char), endhdr - flags, outfile); /* flags */
  174.     fwrite(text,sizeof(char),msg_size,outfile);
  175.  
  176.     if (c == endbuf)        /* made it! */
  177.         exit (0);
  178.     hdrptr = c;            /* move to start of next message*/
  179.     }
  180. }
  181.  
  182. /*
  183.  * alreadyTransformed:
  184.  *     Check to see if a mail file has already been transformed.
  185.  *     Use length of message to see if it predicts the next
  186.  *     header line.
  187.  *     If so, then we suspect the file has been transformed.
  188.  */
  189. alreadyTransformed(mail)
  190. char *mail;
  191. {
  192.     char *msize= index(mail,',') + 1;
  193.     char *nxtmsg, *msgtxt;
  194.     int msglen= atoi(msize);
  195.  
  196.     msgtxt = index(mail,'\n') + 1;    /* text of message itself */
  197.     nxtmsg = msgtxt + msglen;        /* header of next message/NULL */
  198.     if (*nxtmsg == '\0') return(FALSE);    /* Just one message */
  199.     if (ishead(nxtmsg)) return(FALSE);    /* Found a header line */
  200.     return(0);
  201. }
  202.  
  203. /*
  204.  * fail: 
  205.  * give a nice message on failure, tell them which message messed up
  206.  * note that all previous messages were written out successfully
  207.  */
  208. fail (num)
  209. int num;
  210. {
  211.     fprintf (stderr, 
  212.          "Bad mail-txt format in header of message #%d, aborting\n", num);
  213.     exit (1);
  214. }
  215.  
  216. /*
  217.  * ishead:
  218.  * compare str against a regex looking for a header line.
  219.  * since re_exec() ignores \n's, copy the current "line" and
  220.  * then call re_exec().
  221.  */
  222. ishead(str)
  223. char *str;
  224. {
  225.     char buf[BUFSIZ];
  226.     char *p;
  227.     static int first = TRUE;
  228.     int st;
  229.  
  230.     if (first) {
  231.     first = FALSE;
  232.     /* pattern is:         22-Jan-88  3:45:11-GMT,944;000000000201 */
  233.     if ((p = (char *) re_comp(".*-[A-Za-z][A-Za-z][A-Za-z]-.*:[0-5][0-9]:[0-5][0-9]-.*,[0-9]*;[0-9]*" )) != NULL) {
  234.         fprintf("Bad regex: %s\n", p);
  235.         fail(msgnum);
  236.     }
  237.     }
  238.  
  239.     p = index(str, '\n');
  240.     if (p) {
  241.     if ((p - str) > sizeof(buf))
  242.         return(FALSE);        /* too long for a header line */
  243.     strncpy(buf, str, (p - str));
  244.     buf[p - str] = NULL;
  245.     }
  246.     else
  247.     strncpy(buf, str, sizeof(buf));
  248.  
  249.     /* Only pass likely candidates to re_exec for verification */
  250.     if (((p = index(buf, '-')) == NULL) ||
  251.     ((p = index(p+1, '-')) == NULL) ||
  252.     ((p = index(p, ':')) == NULL) ||
  253.     ((p = index(p+1, ':')) == NULL) ||
  254.     ((p = index(p, '-')) == NULL) ||
  255.     ((p = index(p, ',')) == NULL) ||
  256.     ((p = index(p, ';')) == NULL))
  257.     return (FALSE);
  258.  
  259.     st = re_exec(buf);
  260.  
  261.     return(st);
  262. }
  263.